﻿#include "KeyboardLayoutDialog.h"
#include "../../MirGraphics/MLibrary.h"
#include "../../Settings.h"
#include "../../MirSounds/SoundManager.h"
#include "../../Forms/Client.CMain.h"

using namespace Client::MirControls;
using namespace Client::MirGraphics;
using namespace Client::MirSounds;

namespace Client::MirScenes::Dialogs
{

    KeyboardLayoutDialog::KeyboardLayoutDialog()
    {
        setIndex(119);
        setLibrary(Libraries::Title);
        setMovable(true);
        setSort(true);
        setLocation(getCenter());

        TitleLabel = new MirImageControl();
        TitleLabel->setLibrary(Libraries::Title);
        Point tempVar(18, 4);
        TitleLabel->setLocation(&tempVar);
        TitleLabel->setParent(this);

        PageLabel = new MirLabel();
        PageLabel->setText("Keyboard Settings");
        Font tempVar2(Settings::FontName, Settings::FontSize + 2, FontStyle::Bold);
        PageLabel->setFont(&tempVar2);
        PageLabel->setDrawFormat(TextFormatFlags::HorizontalCenter | TextFormatFlags::VerticalCenter);
        PageLabel->setParent(this);
        System::Drawing::Size tempVar3(242, 30);
        PageLabel->setSize(&tempVar3);
        Point tempVar4(135, 34);
        PageLabel->setLocation(&tempVar4);

        CloseButton = new MirButton();
        CloseButton->setHoverIndex(361);
        CloseButton->setIndex(360);
        Point tempVar5(489, 3);
        CloseButton->setLocation(&tempVar5);
        CloseButton->setLibrary(Libraries::Prguse2);
        CloseButton->setParent(this);
        CloseButton->setPressedIndex(362);
        CloseButton->setSound(SoundList::ButtonA);
        CloseButton->Click += [&] (o, e)
        {
            Hide();
        };

        ScrollUpButton = new MirButton();
        ScrollUpButton->setIndex(197);
        ScrollUpButton->setHoverIndex(198);
        ScrollUpButton->setPressedIndex(199);
        ScrollUpButton->setLibrary(Libraries::Prguse2);
        ScrollUpButton->setParent(this);
        Size tempVar6(16, 14);
        ScrollUpButton->setSize(&tempVar6);
        Point tempVar7(491, 88);
        ScrollUpButton->setLocation(&tempVar7);
        ScrollUpButton->setSound(SoundList::ButtonA);
        ScrollUpButton->setVisible(true);

        ScrollUpButton->Click += [&] (o, e)
        {
            if (TopLine <= 0)
            {
                return;
            }
    
            TopLine--;
    
            UpdateText();
            UpdatePositionBar();
        };

        ScrollDownButton = new MirButton();
        ScrollDownButton->setIndex(207);
        ScrollDownButton->setHoverIndex(208);
        ScrollDownButton->setLibrary(Libraries::Prguse2);
        ScrollDownButton->setPressedIndex(209);
        ScrollDownButton->setParent(this);
        Size tempVar8(16, 14);
        ScrollDownButton->setSize(&tempVar8);
        Point tempVar9(491, 363);
        ScrollDownButton->setLocation(&tempVar9);
        ScrollDownButton->setSound(SoundList::ButtonA);
        ScrollDownButton->setVisible(true);

        ScrollDownButton->Click += [&] (o, e)
        {
            if (TopLine + LineCount >= CMain::InputKeys->Keylist.size() + CMain::InputKeys->Keylist.GroupBy([&] (std::any x)
            {
                x::Group;
            })->Select([&] (std::any y)
            {
                y::First();
            })->Count())return;
            {
    
            TopLine++;
            }
    
            UpdateText();
            UpdatePositionBar();
        };

        PositionBar = new MirButton();
        PositionBar->setIndex(205);
        PositionBar->setHoverIndex(206);
        PositionBar->setPressedIndex(206);
        PositionBar->setLibrary(Libraries::Prguse2);
        Point tempVar10(491, 101);
        PositionBar->setLocation(&tempVar10);
        PositionBar->setParent(this);
        PositionBar->setMovable(true);
        PositionBar->setSound(SoundList::None);
        PositionBar->setVisible(true);
        PositionBar->OnMoving->addListener("PositionBar_OnMoving", std::bind(&KeyboardLayoutDialog::PositionBar_OnMoving, this, std::placeholders::_1, std::placeholders::_2));


        ResetButton = new MirButton();
        ResetButton->setIndex(120);
        ResetButton->setHoverIndex(121);
        ResetButton->setPressedIndex(122);
        ResetButton->setLibrary(Libraries::Title);
        Size tempVar11(72, 25);
        ResetButton->setSize(&tempVar11);
        Point tempVar12(30, 400);
        ResetButton->setLocation(&tempVar12);
        ResetButton->setParent(this);
        ResetButton->setVisible(true);
        ResetButton->Click += [&] (o, e)
        {
            for (int i = 0; i < CMain::InputKeys->Keylist.size(); i++)
            {
                KeyBind *bind = CMain::InputKeys->Keylist[i];
                KeyBind *defaultBind = CMain::InputKeys->DefaultKeylist[i];
    
                if (bind->Key != defaultBind->Key || bind->RequireAlt != defaultBind->RequireAlt || bind->RequireCtrl != defaultBind->RequireCtrl || bind->RequireShift != defaultBind->RequireShift || bind->RequireTilde != defaultBind->RequireTilde)
                {
                    CMain::InputKeys->Keylist[i]->Key = defaultBind->Key;
                    CMain::InputKeys->Keylist[i]->RequireAlt = defaultBind->RequireAlt;
                    CMain::InputKeys->Keylist[i]->RequireCtrl = defaultBind->RequireCtrl;
                    CMain::InputKeys->Keylist[i]->RequireShift = defaultBind->RequireShift;
                    CMain::InputKeys->Keylist[i]->RequireTilde = defaultBind->RequireTilde;
    
                    //CMain.Profile.InputKeys.Save(CMain.Profile.InputKeys.Keylist[i]);
                }
            }
    
            UpdateText();
    
            MirMessageBox *messageBox = new MirMessageBox("Keyboard settings have been reset back to default.", MirMessageBoxButtons::OK);
            messageBox->Show();

            delete messageBox;
        };

        EnforceButton = new MirButton();
        EnforceButton->setVisible(true);
        EnforceButton->setIndex(1346);
        EnforceButton->setLibrary(Libraries::Prguse);
        EnforceButton->setSound(SoundList::ButtonA);
        EnforceButton->setParent(this);
        Point tempVar13(105, 406);
        EnforceButton->setLocation(&tempVar13);
        EnforceButton->Click += EnforceButton_Click;

        EnforceButtonChecked = new MirImageControl();
        EnforceButtonChecked->setVisible(Enforce);
        EnforceButtonChecked->setIndex(1347);
        EnforceButtonChecked->setLibrary(Libraries::Prguse);
        EnforceButtonChecked->setParent(this);
        EnforceButtonChecked->setNotControl(true);
        Point tempVar14(105, 406);
        EnforceButtonChecked->setLocation(&tempVar14);

        EnforceButtonLabel = new MirLabel();
        EnforceButtonLabel->setVisible(true);
        EnforceButtonLabel->setNotControl(true);
        EnforceButtonLabel->setParent(this);
        Point tempVar15(120, 404);
        EnforceButtonLabel->setLocation(&tempVar15);
        EnforceButtonLabel->setAutoSize(true);
        EnforceButtonLabel->setText("Assign Rule: Strict");

        UpdateText();
    }

    void KeyboardLayoutDialog::EnforceButton_Click(std::any sender, EventArgs *e)
    {
        Enforce = !Enforce;

        EnforceButtonChecked->setVisible(Enforce);

        if (Enforce)
        {
            EnforceButtonLabel->setText("Assign Rule: Strict");
        }
        else
        {
            EnforceButtonLabel->setText("Assign Rule: Relaxed");
        }
    }

    void KeyboardLayoutDialog::UpdateText()
    {
        for (auto t : Rows)
        {
            t->Dispose();
        }

        Rows.clear();

        auto orderedList = CMain::InputKeys->Keylist.OrderBy([&] (std::any x)
        {
            x::Group;
        }).ThenBy([&] (std::any x)
        {
            x::Description;
        }).ToList();

        std::string currentGroup = "";
        int groupCount = 0;

        for (int i = 0; i < orderedList.size(); i++)
        {
            if (i < TopLine)
            {
                continue;
            }

            int y = (18 * (i - TopLine)) + (groupCount * 30);

            if (y > 260)
            {
                break;
            }

            if (currentGroup != orderedList[i].Group)
            {
                KeybindHeadingRow *tempVar = new KeybindHeadingRow(orderedList[i].Group);
                tempVar->setParent(this);
                Point tempVar2(15, 90 + y);
                tempVar->setLocation(&tempVar2);
                tempVar->setVisible(true);
                Size tempVar3(400, 40);
                tempVar->setSize(&tempVar3);
                Rows.push_back(tempVar);

                groupCount++;
                currentGroup = orderedList[i].Group;

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
            }

            y = (18 * (i - TopLine)) + (groupCount * 30);

            if (y > 260)
            {
                break;
            }

            KeybindRow *tempVar4 = new KeybindRow(orderedList[i].function);
            tempVar4->setParent(this);
            Point tempVar5(20, 90 + y);
            tempVar4->setLocation(&tempVar5);
            tempVar4->setVisible(true);
            Size tempVar6(460, 15);
            tempVar4->setSize(&tempVar6);
            Rows.push_back(tempVar4);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar4' statement was not added since tempVar4 was passed to a method or constructor. Handle memory management manually.
        }
    }

    void KeyboardLayoutDialog::UpdatePositionBar()
    {
        if (CMain::InputKeys->Keylist.size() <= LineCount)
        {
            PositionBar->setVisible(false);
            return;
        }

        PositionBar->setVisible(true);

        int interval = (PosMaxY - PosMinY) / (CMain::InputKeys->Keylist.size() - LineCount);

        int x = PosX;
        int y = PosMinY + (TopLine * interval);

        if (y >= PosMaxY)
        {
            y = PosMaxY;
        }
        if (y <= PosMinY)
        {
            y = PosMinY;
        }


        Point tempVar(x, y);
        PositionBar->setLocation(&tempVar);
    }

    void KeyboardLayoutDialog::PositionBar_OnMoving(std::any sender, MouseEventArgs *e)
    {
        int x = PosX;
        int y = PositionBar->getLocation()->Y;

        if (y >= PosMaxY)
        {
            y = PosMaxY;
        }
        if (y <= PosMinY)
        {
            y = PosMinY;
        }

        int location = y - PosMinY;
        int interval = (PosMaxY - PosMinY) / (CMain::InputKeys->Keylist.size() - LineCount);

        double yPoint = static_cast<double>(location) / interval;

        TopLine = static_cast<short>(std::floor(yPoint));

        Point tempVar(x, y);
        PositionBar->setLocation(&tempVar);

        UpdateText();
    }

    void KeyboardLayoutDialog::CheckNewInput(KeyEventArgs *e)
    {
        if (e->KeyCode == Keys->ControlKey || e->KeyCode == Keys->Menu || e->KeyCode == Keys->ShiftKey || e->KeyCode == Keys->Oem8 || e->KeyCode == Keys->None)
        {
            return;
        }

        KeyBind *bind = CMain::InputKeys->Keylist.Single([&] (std::any x)
        {
            return x->function == WaitingForBind->function;
        });

        //if (CMain.Profile.InputKeys.Keylist.Any(x => x.Key == e.KeyCode && x.RequireAlt == (byte)(CMain.Alt ? 1 : 0) && x.RequireShift == (byte)(CMain.Shift ? 1 : 0) && x.RequireCtrl == (byte)(CMain.Ctrl ? 1 : 0) && x.RequireTilde == (byte)(CMain.Tilde ? 1 : 0)))
        //{
        //    GameScene.Scene.ChatDialog.ReceiveChat("Another shortcut with this key bind already exists.", ChatType.System);
        //    WaitingForBind = null;
        //    UpdateText();
        //    return;
        //}

        if (e->KeyCode == Keys->Delete)
        {
            bind->Key = Keys->None;
            bind->RequireAlt = bind->RequireShift = bind->RequireCtrl = bind->RequireTilde = 2;
        }
        else
        {
            bind->Key = e->KeyCode;
            bind->RequireAlt = static_cast<unsigned char>(CMain::Alt ? 1 : Enforce ? 0 : 2);
            bind->RequireShift = static_cast<unsigned char>(CMain::Shift ? 1 : Enforce ? 0 : 2);
            bind->RequireCtrl = static_cast<unsigned char>(CMain::Ctrl ? 1 : Enforce ? 0 : 2);
            bind->RequireTilde = static_cast<unsigned char>(CMain::Tilde ? 1 : Enforce ? 0 : 2);
        }

        //CMain.Profile.InputKeys.Save(WaitingForBind);
        WaitingForBind = nullptr;
        UpdateText();
    }

    KeybindRow::KeybindRow(KeybindOptions option)
    {
        KeyBind *defaultBind = CMain::InputKeys->DefaultKeylist.Single([&] (std::any x)
        {
            return x->function == option;
        });
        KeyBind *currentBind = CMain::InputKeys->Keylist.Single([&] (std::any x)
        {
            return x->function == option;
        });

        KeyBind = currentBind;

        BindName = new MirLabel();
        BindName->setParent(this);
        Size tempVar(200, 15);
        BindName->setSize(&tempVar);
        Point tempVar2(0, 0);
        BindName->setLocation(&tempVar2);
        BindName->setText(defaultBind->Description);
        BindName->setVisible(true);

        DefaultBind = new MirLabel();
        DefaultBind->setParent(this);
        Size tempVar3(100, 15);
        DefaultBind->setSize(&tempVar3);
        Point tempVar4(200, 0);
        DefaultBind->setLocation(&tempVar4);
        DefaultBind->setText(CMain::InputKeys->GetKey(option, true));
        DefaultBind->setVisible(true);

        CurrentBindButton = new MirButton();
        CurrentBindButton->setParent(this);
        CurrentBindButton->setText(StringHelper::formatSimple("  {0}", CMain::InputKeys->GetKey(option, false)));
        Point tempVar5(340, 0);
        CurrentBindButton->setLocation(&tempVar5);
        Size tempVar6(120, 16);
        CurrentBindButton->setSize(&tempVar6);
        CurrentBindButton->setVisible(true);
        CurrentBindButton->setIndex(190);
        CurrentBindButton->setLibrary(Libraries::Prguse2);
        CurrentBindButton->setHoverIndex(191);
        CurrentBindButton->setPressedIndex(192);
        CurrentBindButton->Click += [&] (o, e)
        {
            if (GameScene::Scene->KeyboardLayoutDialog->WaitingForBind != nullptr)
            {
                GameScene::Scene->KeyboardLayoutDialog->WaitingForBind = nullptr;
                GameScene::Scene->KeyboardLayoutDialog->UpdateText();
                return;
            }
    
            GameScene::Scene->KeyboardLayoutDialog->WaitingForBind = KeyBind;
    
            (static_cast<MirButton*>(o))->setText(StringHelper::formatSimple("  {0}", "????"));
            (static_cast<MirButton*>(o))->setIndex(192);
            (static_cast<MirButton*>(o))->setHoverIndex(192);
            (static_cast<MirButton*>(o))->setPressedIndex(192);
        };

    }

    KeybindHeadingRow::KeybindHeadingRow(const std::string &groupName)
    {
        BulletImage = new MirImageControl();
        BulletImage->setParent(this);
        BulletImage->setIndex(201);
        BulletImage->setLibrary(Libraries::Prguse2);
        Size tempVar(8, 6);
        BulletImage->setSize(&tempVar);
        Point tempVar2(10, 10);
        BulletImage->setLocation(&tempVar2);
        BulletImage->setVisible(true);

        BulletLabel = new MirLabel();
        BulletLabel->setParent(this);
        BulletLabel->setText(groupName);
        Size tempVar3(100, 20);
        BulletLabel->setSize(&tempVar3);
        Point tempVar4(20, 5);
        BulletLabel->setLocation(&tempVar4);
        Font tempVar5(Settings::FontName, Settings::FontSize + 1, FontStyle::Bold);
        BulletLabel->setFont(&tempVar5);
        BulletLabel->setVisible(true);

        SpacerImage = new MirImageControl();
        SpacerImage->setParent(this);
        SpacerImage->setIndex(202);
        SpacerImage->setLibrary(Libraries::Prguse2);
        Size tempVar6(3, 464);
        SpacerImage->setSize(&tempVar6);
        Point tempVar7(0, 25);
        SpacerImage->setLocation(&tempVar7);
        SpacerImage->setVisible(true);
    }
}
